package com.kexilo.core.common.utils;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * 数组工具类
 * 
 * @author Kexilo
 */
public class ArrayUtils {

    /**
     * 数组是否为空
     * 
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 数组是否不为空
     * 
     * @param array 数组
     * @return 是否不为空
     */
    public static boolean isNotEmpty(Object[] array) {
        return !isEmpty(array);
    }

    /**
     * 合并数组
     * 
     * @param array1 数组1
     * @param array2 数组2
     * @return 合并后的数组
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] addAll(T[] array1, T... array2) {
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        }
        final Class<?> type1 = array1.getClass().getComponentType();
        @SuppressWarnings("unchecked")
        T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
        try {
            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
        } catch (final ArrayStoreException ase) {
            final Class<?> type2 = array2.getClass().getComponentType();
            if (!type1.isAssignableFrom(type2)) {
                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
                        + type1.getName(), ase);
            }
            throw ase;
        }
        return joinedArray;
    }

    /**
     * 克隆数组
     * 
     * @param array 数组
     * @return 克隆的数组
     */
    public static <T> T[] clone(T[] array) {
        if (array == null) {
            return null;
        }
        return array.clone();
    }

    /**
     * 数组中是否包含元素
     * 
     * @param array 数组
     * @param objectToFind 查找的元素
     * @return 是否包含
     */
    public static boolean contains(Object[] array, Object objectToFind) {
        return indexOf(array, objectToFind) != -1;
    }

    /**
     * 返回数组中指定元素所在位置，未找到返回-1
     * 
     * @param array 数组
     * @param objectToFind 要查找的元素
     * @return 位置
     */
    public static int indexOf(Object[] array, Object objectToFind) {
        if (array == null) {
            return -1;
        }
        if (objectToFind == null) {
            for (int i = 0; i < array.length; i++) {
                if (array[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0; i < array.length; i++) {
                if (objectToFind.equals(array[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 包装数组对象
     */
    public static Object[] wrap(Object array) {
        if (array == null) {
            return null;
        }
        if (isWrapperArray(array)) {
            return (Object[]) array;
        }
        int length = Array.getLength(array);
        Object[] result = new Object[length];
        for (int i = 0; i < length; i++) {
            result[i] = Array.get(array, i);
        }
        return result;
    }

    /**
     * 判断数组对象是否为包装数组
     */
    public static boolean isWrapperArray(Object array) {
        return array instanceof Object[];
    }

    /**
     * 判断数组对象是否为基本类型数组
     */
    public static boolean isPrimitiveArray(Object array) {
        return array != null && array.getClass().isArray() && array.getClass().getComponentType().isPrimitive();
    }

    /**
     * 数组转字符串
     * 
     * @param array 数组
     * @return 字符串
     */
    public static String toString(Object array) {
        if (array == null) {
            return "null";
        }
        if (isPrimitiveArray(array)) {
            if (array instanceof boolean[]) {
                return Arrays.toString((boolean[]) array);
            }
            if (array instanceof byte[]) {
                return Arrays.toString((byte[]) array);
            }
            if (array instanceof char[]) {
                return Arrays.toString((char[]) array);
            }
            if (array instanceof double[]) {
                return Arrays.toString((double[]) array);
            }
            if (array instanceof float[]) {
                return Arrays.toString((float[]) array);
            }
            if (array instanceof int[]) {
                return Arrays.toString((int[]) array);
            }
            if (array instanceof long[]) {
                return Arrays.toString((long[]) array);
            }
            if (array instanceof short[]) {
                return Arrays.toString((short[]) array);
            }
        }
        return Arrays.toString((Object[]) array);
    }
}
